package mcom.xmks.bluetooth.mesh.core;

import android.app.Activity;
import android.os.Build;

import java.lang.ref.WeakReference;
import java.util.List;
import java.util.function.Consumer;

import cn.wch.meshlib.frame.ack.AckFrame;
import io.reactivex.Emitter;
import io.reactivex.Observable;
import io.reactivex.ObservableOnSubscribe;
import io.reactivex.Observer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.annotations.NonNull;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
import mcom.xmks.bluetooth.mesh.dialog.DialogUtil;
import mcom.xmks.bluetooth.mesh.utils.LogTool;

public class DataModel {
    private  WeakReference<Activity> activity=null;
    private static volatile DataModel model;
    /**
     * 获取MeshServer实例
     * @return
     */
    public static DataModel getInstance() {
        if(model==null){
            synchronized (DataModel.class){
                model=new DataModel();
            }
        }
        return model;
    }

    public final void attachToActivity(WeakReference<Activity> activity){
        this.activity=activity;
    }
    public final void detachActivity(){
        this.activity=null;
    }

    /**
     *
     * @param activity
     * @param message
     * @param runnable
     * @param callback
     * @param <T>
     */
    public final <T> void rxjavaExecute(Activity activity, String message,CallbackRunnable<T> runnable,Emitter<T> callback){
        Observable.create((ObservableOnSubscribe<T>) emitter->{
                    try {
                        T t= runnable.onRunnable();
                        if(t==null){
                            emitter.onError(new Throwable("fail"));
                            return;
                        }
                        emitter.onNext(t);
                    }catch ( Exception e){
                        LogTool.d("rxjava exception:"+e.getMessage());
                        emitter.onError(new Throwable(e.getMessage()));
                        return;
                    }
                    emitter.onComplete();
                })
                .subscribeOn(Schedulers.newThread())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer<T>() {
                    @Override
                    public void onSubscribe(Disposable d) {
                        if(activity!=null ){
                            DialogUtil.getInstance().showLoadingDialog(activity,message);
                        }
                    }
                    @Override
                    public void onNext(T t) {
                        if(callback!=null)
                            callback.onNext(t);
                    }

                    @Override
                    public void onError(Throwable e) {
                        if(activity!=null){
                            DialogUtil.getInstance().hideLoadingDialog();
                        }
                        if(callback!=null)
                            callback.onError(e);
                    }

                    @Override
                    public void onComplete() {
                        if(activity!=null){
                            DialogUtil.getInstance().hideLoadingDialog();
                        }
                        if(callback!=null)
                            callback.onComplete();
                    }
                });
    }

    /**
     *
     * @param activity 活动对象
     * @param message 消息
     * @param callback 观察者回调
     * @param <T>
     */
    public final <T> void rxjavaExecute(Activity activity, String message,EmitterCallback<T> callback){
        Observable.create((ObservableOnSubscribe<T>) emitter->{
                    try {
                        T t=callback.onRunnable();
                        if(t==null){
                            emitter.onError(new Throwable("fail"));
                            return;
                        }
                        emitter.onNext(t);
                    }catch ( Exception e){
                        LogTool.d("rxjava exception:"+e.getMessage());
                        emitter.onError(new Throwable(e.getMessage()));
                        return;
                    }
                    emitter.onComplete();
                })
                .subscribeOn(Schedulers.newThread())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer<T>() {
                    @Override
                    public void onSubscribe(Disposable d) {
                        if(activity!=null ){
                            DialogUtil.getInstance().showLoadingDialog(activity,message);
                        }
                    }

                    @Override
                    public void onNext(T t) {
                        if(callback!=null)
                            callback.onNext(t);
                    }

                    @Override
                    public void onError(Throwable e) {
                        if(activity!=null){
                            DialogUtil.getInstance().hideLoadingDialog();
                        }
                        if(callback!=null)
                            callback.onError(e);
                    }
                    @Override
                    public void onComplete() {
                        if(activity!=null){
                            DialogUtil.getInstance().hideLoadingDialog();
                        }
                        if(callback!=null)
                            callback.onComplete();
                    }
                });
    }

    public final  <T> void rxjavaExecuteAll(Activity activity, String message, List<T> list, Emitter<T> callback){
        Observable.create((ObservableOnSubscribe<T>) emitter->{
                    for (T t : list){
                        try {
                            if(t!=null){
                                emitter.onNext(t);
                            }
                        }catch ( Exception e){
                            LogTool.d("rxjava exception:"+e.getMessage());
                        }
                    }
                    emitter.onComplete();
                }).subscribeOn(Schedulers.newThread())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer<T>() {
                    @Override
                    public void onSubscribe(Disposable d) {
                        if(activity!=null){
                            DialogUtil.getInstance().showLoadingDialog(activity,message);
                        }
                    }
                    @Override
                    public void onNext(T t) {
                        if(callback!=null)
                            callback.onNext(t);
                    }

                    @Override
                    public void onError(Throwable e) {
                        if(activity!=null){
                            DialogUtil.getInstance().hideLoadingDialog();
                        }
                        if(callback!=null)
                            callback.onError(e);
                    }

                    @Override
                    public void onComplete() {
                        if(activity!=null){
                            DialogUtil.getInstance().hideLoadingDialog();
                        }
                        if(callback!=null)
                            callback.onComplete();
                    }
                });
    }

    /**
     *
     * @param activity
     * @param message
     * @param list
     * @param callback
     * @param <T>
     */
    public final  <T> void rxjavaExecuteAllE(Activity activity, String message, List<T> list, Emitter<T> callback){
        if(list!=null) {
            if(activity!=null){
                DialogUtil.getInstance().showLoadingDialog(activity,message);
            }
            new Thread(() -> {
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                        list.forEach(t -> callback.onNext(t));
                    } else {
                        for (T t : list) {
                            callback.onNext(t);
                        }
                    }
                if(activity!=null){
                    DialogUtil.getInstance().hideLoadingDialog();
                }
                callback.onComplete();
            }).start();
        }
    }
    public final  <T> void  rxjavaExecuteAny(Activity activity, String message, List<T> list,
                                             CallbackShouldContinue shouldContinue,Emitter<T> callback){
        Observable.create((ObservableOnSubscribe<T>) emitter -> {
                    try {
                        for(int i=0;i<list.size();i++){
                            T t=list.get(i);
                            if(t==null){
                                emitter.onError(new Throwable("fail"));
                                return;
                            }
                            if(shouldContinue!=null) {
                                if (!shouldContinue.onShouldContinue(t)) {
                                    emitter.onError(new Throwable("fail"));
                                    return;
                                }
                            }
                            emitter.onNext(t);
                        }
                    } catch (Exception e) {
                        LogTool.d("rxjava exception:"+e.getMessage());
                        emitter.onError(e);
                        return;
                    }
                    emitter.onComplete();
                })
                .subscribeOn(Schedulers.newThread())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer<T>() {
                    @Override
                    public void onSubscribe(Disposable d) {
                        if(activity!=null){
                            DialogUtil.getInstance().showLoadingDialog(activity,message);
                        }
                    }
                    @Override
                    public void onNext(T t) {
                        if(callback!=null)
                            callback.onNext(t);
                    }
                    @Override
                    public void onError(Throwable e) {
                        if(activity!=null){
                            DialogUtil.getInstance().hideLoadingDialog();
                        }
                        if(callback!=null)
                            callback.onError(e);
                    }

                    @Override
                    public void onComplete() {
                        if(activity!=null){
                            DialogUtil.getInstance().hideLoadingDialog();
                        }
                        if(callback!=null)
                            callback.onComplete();
                    }
                });
    }
    public interface CallbackShouldContinue<T>{
        boolean onShouldContinue(T t);
    }
    public interface CallbackRunnable<T>{
       <T>T onRunnable() ;
    }


    public interface EmitterCallback<T> {
        /**运行中*/
        <T>T onRunnable() ;
        /**
         * 发出正常值的信号。
         * @param value 信号的值，而不是null
         */
        void onNext(@NonNull T value);

        /**
         * 发出可抛出的异常信号。
         * @param error 可抛出的信号，而不是null
         */
        void onError(@NonNull Throwable error);

        /**
         * 信号完成
         */
        void onComplete();
    }
}
